package com.fqgame.user.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fqgame.user.entity.UserInfo;
import com.fqgame.user.mapper.UserInfoMapper;
import com.fqgame.user.service.PointsRecordService;
import com.fqgame.user.service.UserInfoService;
import com.fqgame.user.service.UserOrderService;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * 用户信息服务实现类
 */
@Slf4j
@Service
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {

    @Autowired
    private UserOrderService userOrderService;

    @Autowired
    private PointsRecordService pointsRecordService;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 创建订单并扣减余额（分布式事务示例）
     * 使用Seata的@GlobalTransactional注解实现分布式事务
     */
    @Override
    @GlobalTransactional(name = "create-order-tx", rollbackFor = Exception.class)
    public Long createOrderWithTransaction(Long userId, Long productId, String productName, BigDecimal amount) {
        log.info("开始创建订单并扣减余额，用户ID：{}，商品ID：{}，金额：{}", userId, productId, amount);
        
        // 1. 检查用户余额
        UserInfo userInfo = this.getById(userId);
        if (userInfo == null) {
            throw new RuntimeException("用户不存在");
        }
        
        if (userInfo.getBalance().compareTo(amount) < 0) {
            throw new RuntimeException("用户余额不足");
        }
        
        // 2. 扣减用户余额
        int result = baseMapper.updateBalance(userId, amount.negate());
        if (result <= 0) {
            throw new RuntimeException("扣减余额失败");
        }
        
        // 3. 创建订单（可能是远程服务调用）
        Long orderId = userOrderService.createOrder(userId, productId, productName, amount);
        
        // 4. 发送消息更新积分（异步操作）
        sendPointsUpdateMessage(userId, amount.intValue() / 10, "购买商品");
        
        log.info("订单创建成功，订单ID：{}", orderId);
        return orderId;
    }

    /**
     * 更新用户积分（消息队列示例）
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateUserPoints(Long userId, Integer points, String reason) {
        log.info("更新用户积分，用户ID：{}，积分：{}，原因：{}", userId, points, reason);
        
        // 1. 更新用户积分
        int result = baseMapper.updatePoints(userId, points);
        if (result <= 0) {
            throw new RuntimeException("更新积分失败");
        }
        
        // 2. 添加积分记录
        int type = points > 0 ? 1 : 2;
        boolean success = pointsRecordService.addPointsRecord(
                userId, Math.abs(points), type, reason, UUID.randomUUID().toString());
        
        if (!success) {
            throw new RuntimeException("添加积分记录失败");
        }
        
        log.info("用户积分更新成功，用户ID：{}", userId);
    }

    /**
     * 定时统计用户数据（任务调度示例）
     */
    @Override
    public void statisticsUserData() {
        log.info("开始统计用户数据，时间：{}", LocalDateTime.now());
        
        // 模拟统计逻辑
        long totalUsers = this.count();
        log.info("用户总数：{}", totalUsers);
        
        // 实际场景中可能需要更复杂的统计逻辑
        // ...
        
        log.info("用户数据统计完成");
    }

    /**
     * 发送积分更新消息到RabbitMQ
     */
    private void sendPointsUpdateMessage(Long userId, Integer points, String reason) {
        Map<String, Object> message = new HashMap<>();
        message.put("userId", userId);
        message.put("points", points);
        message.put("reason", reason);
        message.put("timestamp", System.currentTimeMillis());
        
        rabbitTemplate.convertAndSend("user.points", "user.points.update", message);
        log.info("积分更新消息已发送，用户ID：{}，积分：{}", userId, points);
    }
}